<template>
	<!-- 三维画布 -->
	<div ref="draw" class="draw"></div>
</template>

<script>
	import * as THREE from 'three'; // 三维
	import {
		OrbitControls
	} from 'three/examples/jsm/controls/OrbitControls.js'; // 控制器

	export default {
		name: 'drawModel', // 三维画布
		props: {
			// // 传入模型函数
			// initLoader: {
			//   type: [Function],
			// },
			// 传入光源数组
			respond_meshs: {
				type: [Array],
				default: () => {
					return [];
				},
			},
			metalMaterial: {
				type: [Object],
				default: () => {
					return {
						color: new THREE.Color(0.1, 0.1, 0.1), // 金属的基础颜色
						specular: 0xffffff, // 高光颜色，金属通常反射白色高光
						shininess: 30, // 光泽度，值越大越光亮
						reflectivity: 1, // 反射率，金属的反射率通常较高
					};
				},
			},
			lightlist: {
				type: [Array],
				default: () => {
					return [{
						type: 'AmbientLight', // 光的类型
						color: 0xffffff, // 光的颜色
						intensity: 1, // 光照强度
						posiy: [0, 0, 0], // 光照位置
					}, ];
				},
			},
			// 传入相机对象
			sightline: {
				type: [Object],
				default: () => {
					return {
						scale: 200, // 视线比例
						type: 'OrthographicCamera', // 相机的类型
						posiy: [200, 300, 200], // 相机位置
					};
				},
			},
			// 传入渲染对象
			strain: {
				type: [Object],
				default: () => {
					return {
						color: '#FFFFFF', // 背景颜色
						Encoding: false, // 色彩空间
						shadow: false, // 渲染阴影
					};
				},
			},
			// 是否开启鼠标控制
			orbit: {
				type: [Boolean],
				default: true,
			},
		},
		data() {
			return {
				scene: null, // 场景对象Scene
				camera: null, // 相机对象
				draw: null, // 节点对象
				renderer: null, // 渲染器对象
				controls: null, // 控件对象
				movetype: -1, // 鼠标事件，默认-1（0点击，1移动
				isclick: null, // 判断鼠标状态
				interSected: null,
				sprite: null,
			};
		},
		mounted() {
			// 初始化渲染
			this.init();
			// 初始化控制
			this.orbitControls();
			// 条添加事件
			this.addmeth();
			// 设置动画
			this.tweenUpdate();
			this.$emit('initLoader');
		},
		methods: {
			init() {
				//  初始化场景对象
				this.initScene();
				// 初始化光源
				this.initLight();
				// 初始化相机
				this.initCamera();
				// 初始化渲染对象
				this.initRenderer();
				// 渲染操作
				this.animation();
			},
			// 初始化场景对象
			initScene() {
				// 初始化场景对象
				this.scene = new THREE.Scene();
				this.scene.background = null;
				// 创建三维坐标系
				// var axesHelper = new THREE.AxesHelper(100);
				// this.scene.background = new THREE.Color(0x000a22);
				// this.scene.add(axesHelper);
			},
			// 初始化光源
			initLight() {
				// 遍历添加光源
				console.log(this.lightlist, 'this.lightlist');

				this.lightlist.forEach((item) => {
					// light.position.set(item.posiy[0], item.posiy[1], item.posiy[2]); // 点光源位置
					if (item.type === 'DirectionalLight') {
						var light = new THREE.DirectionalLight(item.color);
						light.position.set(item.posiy[0], item.posiy[1], item.posiy[2]);
						light.castShadow = true;
						this.scene.add(light);
						// 开启指示器
					} else if (item.type === 'HemisphereLight') {
						var light2 = new THREE.HemisphereLight(item.color, item.intensity);
						light2.position.set(item.posiy[0], item.posiy[1], item.posiy[2]);
						this.scene.add(light2);
					}
				});
			},
			// 初始化相机
			initCamera() {
				var k = this.$refs.draw.offsetWidth / this.$refs.draw.offsetHeight; // 窗口宽高比
				// 创建相机对象

				this.camera = new THREE.PerspectiveCamera(this.sightline.scale, k, 1, 100000);
				console.log(this.camera, 'PerspectiveCamera');
				console.log(this.sightline.posiy, 'this.sightline.posiy');

				// 红 绿 蓝
				this.camera.position.set(this.sightline.posiy[0], this.sightline.posiy[1], this.sightline.posiy[
				2]); // 设置相机位置
				this.camera.lookAt(this.scene.position); // 设置相机方向(指向的场景对象)
			},
			// 渲染器对象
			initRenderer() {
				// 渲染器对象
				this.renderer = new THREE.WebGLRenderer({
					antialias: true,
					alpha: true
				});
				// 设置渲染区域尺寸
				this.renderer.setSize(this.$refs.draw.offsetWidth, this.$refs.draw.offsetHeight);
				// three.js 的色彩空间渲染方式  【重要】
				if (this.strain.Encoding) {
					this.renderer.outputEncoding = THREE.sRGBEncoding;
				}
				if (this.strain.shadow) {
					// 开启渲染阴影
					this.renderer.shadowMap.enabled = true;
					this.renderer.hadowMapEnabled = true;
				}
				this.renderer.setClearColor(this.strain.color, 0); // 设置背景颜色
				// body元素中插入canvas对象
				this.$refs.draw.appendChild(this.renderer.domElement);
			},
			// 执行渲染操作
			animation() {
				// 执行渲染操作
				this.renderer.render(this.scene, this.camera);
				requestAnimationFrame(this.animation);
			},
			// 初始化控制
			orbitControls() {
				if (this.orbit) {
					this.controls = new OrbitControls(this.camera, this.renderer.domElement); // 创建控件对象
				}
			},
			// 添加全局方法
			addmeth() {
				// 监听窗口尺寸变化
				window.addEventListener('resize', this.changeSize, false);
				//监听鼠标点击
				window.addEventListener('click', this.handleClick, false);
			},
			destroyMeth() {
				(this.scene = null), // 场景对象Scene
				(this.camera = null), // 相机对象
				(this.draw = null), // 节点对象
				(this.renderer = null), // 渲染器对象
				(this.controls = null), // 控件对象
				(this.isclick = null), // 判断鼠标状态
				(this.interSected = null),
				(this.sprite = null),
				window.removeEventListener('resize', this.changeSize, false);
				window.removeEventListener('click', this.handleClick, false);
			},
			// 监听尺寸变化
			changeSize() {
				// 重置渲染器输出画布canvas尺寸
				this.renderer.setSize(this.$refs.draw.offsetWidth, this.$refs.draw.offsetHeight);
				var k = this.$refs.draw.offsetWidth / this.$refs.draw.offsetHeight; // 窗口宽高比
				// 重置相机投影的相关参数
				if (this.sightline.type === 'OrthographicCamera') {
					this.camera.left = -this.sightline.scale * k;
					this.camera.right = this.sightline.scale * k;
					this.camera.top = this.sightline.scale;
					this.camera.bottom = -this.sightline.scale;
				} else if (this.sightline.type === 'PerspectiveCamera') {
					this.camera.aspect = k;
				}
				// 如果相机的一些属性发生了变化，
				// 需要执行updateProjectionMatrix ()方法更新相机的投影矩阵
				this.camera.updateProjectionMatrix();
			},
			// 监听鼠标按下
			mouseDown(event) {
				this.isclick = {
					clientX: event.clientX,
					clientY: event.clientY,
				};
			},
			//
			handleClick(event) {
				console.log(event, 'event');
				let that = this;
				let x, y;
				const mouse = new THREE.Vector2();
				if (event.changedTouches) {
					x = event.changedTouches[0].pageX;
					y = event.changedTouches[0].pageY;
				} else {
					x = event.clientX;
					y = event.clientY;
				}
				console.log(x, y, 'xy');
				console.log(this.$refs.draw.offsetWidth, 'offsetWidth');
				mouse.x = (x / this.$refs.draw.offsetWidth) * 2 - 1;
				mouse.y = -(y / this.$refs.draw.offsetHeight) * 2 + 1;
				console.log(mouse, 'mouse');
				this.onHitTargetMouseEvent(
					mouse,
					function(intersects) {
						console.log(intersects, 'intersects');

						if (intersects.length > 0) {
							console.log(that.metalMaterial);

							if (that.interSected) {
								that.interSected.material = new THREE.MeshPhongMaterial(that.metalMaterial);
							}
							that.interSected = intersects[0].object;
							console.log(that.interSected, 'interSected');

							that.interSected.material = new THREE.MeshPhongMaterial({
								color: new THREE.Color(0x25b4db),
							});
						}
					},
					function() {
						console.log('that.interSected', that.interSected);

						if (that.interSected) {
							that.interSected.material = new THREE.MeshPhongMaterial(that.metalMaterial);
						}
						that.interSected = null;
						return;
					}
				);
			},
			onHitTargetMouseEvent(mouse, hitSuccess, hitFailed) {
				const raycaster = new THREE.Raycaster();
				raycaster.setFromCamera(mouse, this.camera);
				// console.log(raycaster);
				var intersects = raycaster.intersectObjects(this.respond_meshs);
				console.log(intersects, 'intersects');
				if (intersects.length > 0) {
					return hitSuccess(intersects);
				} else {
					return hitFailed();
				}
			},
			// 设置动画
			tweenUpdate() {
				// console.log(this.$tweener,'this.$tweener');

				requestAnimationFrame(this.tweenUpdate);
				this.$tweener.update();
			},
			// 运动动画
			tweenobj(object, potion, time) {
				this.$tween.fade(object.position, potion, time, 0, this.$tweener.Easing.Cubic.InOut);
			},
		},

		beforeDestroy() {
			// 销毁方法
			console.log('销毁方法');

			this.destroyMeth();
		},
	};
</script>

<style scoped>
	.draw {
		width: 100%;
		height: 100%;
		z-index: 9999999;
	}
</style>